import {
  Controller,
  Get,
  Post,
  Inject,
  Body,
  Param,
  Files,
  Del,
  Query
} from '@midwayjs/decorator';
import * as fs from 'fs';
import { Context } from '@midwayjs/koa';
// import { createReadStream } from 'fs';
// import { createReadStream, existsSync } from 'fs';
import { v4 as uuidv4 } from 'uuid';
import { FirmwareService } from '../../service/firmware/firmware.service';
import * as path from 'path';
// import { FirmwareType } from '../../entity/enums';
import { UploadMiddleware, UploadFileInfo } from '@midwayjs/busboy';
import { resBuild } from '@utils/resBuild'; // 导入 resBuild 工具类;
@Controller('/firmware')
export class FirmwareController {
  @Inject()
  ctx: Context; // 注入上下文对象
  @Inject()
  firmwareService: FirmwareService;

  // 上传固件 文件
  @Post('/file', { middleware: [UploadMiddleware] })
  async uploadFile(@Files('file') files: UploadFileInfo[] extends { size: number } ? UploadFileInfo[] : any) {
    // 检查上传文件是否存在
    if (!files || files.length === 0) {
      return resBuild.fail('没有上传文件，请选择文件进行上传');
    }

    const file = files[0]; // 取第一个文件
    console.log('file', file);
    // 检查文件类型是否正确
    const allowedTypes = ['.bin'];
    const fileType = path.extname(file.filename).toLowerCase();
    if (!allowedTypes.includes(fileType)) {
      return resBuild.fail('文件类型不正确，请上传 .bin 文件');
    }

    // 文件保存路径
    const uploadDir = path.join(__dirname, '../../upload');
    const fileExt = path.extname(file.filename); // 更安全地获取文件扩展名
    const filePath = path.join(uploadDir, `${uuidv4()}${fileExt}`);

    // 确保上传目录存在
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }

    try {
      // 更安全的类型检查方式
      if (Buffer.isBuffer(file.data)) {
        // 情况1: file.data 是 Buffer
        fs.writeFileSync(filePath, file.data);
      } else if (typeof file.data === 'string') {
        // 情况2: file.data 是文件路径字符串
        fs.copyFileSync(file.data, filePath);
      } else if (typeof (file.data as any).pipe === 'function') {
        // 情况3: file.data 是可读流 (有 pipe 方法)
        const writeStream = fs.createWriteStream(filePath);
        await new Promise((resolve, reject) => {
          (file.data as unknown as NodeJS.ReadableStream).pipe(writeStream)
            .on('finish', resolve)
            .on('error', reject);
        });
      } else {
        throw new Error(`不支持的文件数据类型: ${typeof file.data}`);
      }

      console.log(`文件已成功保存到: ${filePath}`);

      // 通过文件路径计算 checksum
      const fileBuffer = fs.readFileSync(filePath);
      const checksum = await this.calChecksum(fileBuffer); // 计算文件的 checksum
      console.log('checksum', checksum);
      file.checksum = checksum; // 将 checksum 添加到文件对象中
      // 如果 file.checksum > 32位的最大值， 也就是2的32次方-1
      if(file.checksum > 4294967295){
        return resBuild.fail('文件checksum超过限制，请上传小于32位的文件');
      }
      if(file.checksum <= 0){
        return resBuild.fail('文件checksum不对，请上传正确的文件');
      }
      // 保存数据库 firmware_wristband_files
      const result = await this.firmwareService.uploadFile(
        file,
        filePath
      );

      return resBuild.data(result);
    } catch (error) {
      throw new Error(`保存文件失败: ${error.message}`);
    }
  }


  // 计算文件的 checksum
  async calChecksum(buffer: Buffer): Promise<number> {
    let checksum = 0;
    for (let i = 0; i < buffer.length; i++) {
      checksum += buffer[i];
    }
    console.log(`Size: ${buffer.length} bytes`);
    console.log(`Checksum: ${checksum} (0x${checksum.toString(16).toUpperCase()})`);
    return checksum % Math.pow(2, 32); // 限制在32位范围内
  }
  // 创建固件
  @Post('/create')
  async create(@Body() body) {
    console.log('body', body);
    try {
      const { name, version, firmwareType, path, desc, raw, fileid } = body;
      const result = await this.firmwareService.createFirmware(
        name,
        version,
        firmwareType,
        path,
        desc,
        raw,
        fileid
      );
      console.log('result', result);
      return resBuild.success();
    } catch (error) {
      console.log(error, 'errors')
      return resBuild.fail('创建固件出错:', error);
    }
  }


  // 获取所有固件
  // @Get('/list')
  // async list() {
  //   const firmwares = await this.firmwareService.getAllFirmware();
  //   const filteredFirmwares = firmwares.filter(fw => fw.deleted !== true);
  //   return resBuild.data(filteredFirmwares);
  // }

  // 根据 name / version 查询对应固件
  @Get('/list')
  async list(@Query() params) {
    try {
      const firmwares = await this.firmwareService.getAllFirmware(params);
      return resBuild.data(firmwares);
    } catch (err) {
      console.log(err, 'err')
      return resBuild.fail("查询失败");
    }

  }

  // 查询所有固件(根据 bin/fs/gw/wb划分)
  @Get('/list_type')
  async listType() {
    try {
      const firmwares = await this.firmwareService.getFirmwareByType();
      return resBuild.data(firmwares);
    } catch (err) {
      console.log(err, 'err')
      return resBuild.fail("查询失败");
    }

  }

  // 获取单个固件
  @Get('/:id')
  async getById(@Param('id') id: string) {
    const firmware = await this.firmwareService.getFirmwareById(id);
    if (!firmware) return { success: false, message: '固件不存在' };
    return resBuild.data(firmware);
  }

  // **更新固件**
  @Post('/update/:id')
  async update(@Param('id') id: string, @Body() body) {
    return await this.firmwareService.updateFirmware(id, body);
    // console.log('updatebody',body)
    // try {
    //   const updatedFirmware =
    //     await this.firmwareService.updateFirmware(id, body);
    //     console.log('result',updatedFirmware)
    //   if (!updatedFirmware) return resBuild.success('更新成功！');
    // } catch (error) {
    //   return resBuild.fail('更新失败，固件不存在');
    // }
  }

  // **删除固件**
  @Del('/delete/:id')
  async delete(@Param('id') id: string) {
    return await this.firmwareService.deleteFirmware(id);
    // const deleted = await this.firmwareService.deleteFirmware(id);
    // if (!deleted) return { success: false, message: '删除失败，固件不存在' };
    // return { success: true, message: '删除成功' };
  }

  // 下载指定固件并下发到手环
  @Get('/download/:gatewayId/:firmwareId')
  async downloadFirmware(
    @Param('gatewayId') gatewayId: string,
    @Param('firmwareId') firmwareId: string
  ) {
    // 查询指定 ID 的固件
    const firmware = await this.firmwareService.getFirmwareById(
      firmwareId
    );
    if (!firmware) {
      return { code: 404, message: `固件 ID ${firmwareId} 不存在` };
    }

    const filePath = firmware.path;
    if (!filePath || !fs.existsSync(filePath)) {
      return { code: 404, message: `固件文件 ${filePath} 不存在` };
    }

    // 模拟固件下发到手环
    this.firmwareService.sendFirmwareToWristband(gatewayId, firmware);

    return {
      code: 200,
      message: `固件 ${firmware.name} 已成功下发到手环`,
      data: { name: firmware.name, version: firmware.version, file: filePath },
    };
  }


  // 下载固件
  @Get('/downloadUrl')
  async downloadUrlFirmware(
    @Query('fileid') fileid: string,
    @Query('firmware') firmware: string) {
    console.log('Received request with fileid:', fileid, 'and firmware:', firmware);
    try {
      const filepath = await this.firmwareService.getFirmwareFileById(fileid);
      // const uploadDir = path.join(__dirname, filepath);
      console.log('绝对路径:', filepath);
      // 检查文件是否存在
      if (!fs.existsSync(filepath.path)) {
        // this.ctx.status = 404;
        // this.ctx.body = 'File not found on server';
        return resBuild.fail("下载失败，文件不存在");
      } else {
        try {

          // 创建文件流并返回给客户端
          const fileStream = fs.createReadStream(filepath.path);
          fileStream.on('error', (error) => {
            console.error('文件流读取失败:', error);
            this.ctx.status = 500;
            this.ctx.body = '文件流读取失败';
          });
          // 设置响应头
          this.ctx.set('Content-Disposition', `attachment; filename=${filepath.name}`);
          this.ctx.set('Content-Type', 'application/octet-stream');
          this.ctx.status = 200;
          // 返回文件流
          this.ctx.body = fileStream;
        } catch (error) {
          this.ctx.status = 500;
          this.ctx.body = 'Failed to download file';
          return resBuild.fail("文件下载失败")
        }
      }

    } catch (err) {
      console.log('err', err)
      return resBuild.fail("文件下载失败", err)
    }
  }

}
